Skip to content

feat(services): progressive referral rail and compact result rows (#163) - #1982

Merged
BigSimmo merged 13 commits into
mainfrom
claude/services-search-redesign-163
Aug 15, 2026
Merged

feat(services): progressive referral rail and compact result rows (#163)#1982
BigSimmo merged 13 commits into
mainfrom
claude/services-search-redesign-163

Conversation

@BigSimmo

Copy link
Copy Markdown
Owner

Summary

  • Re-measured ledger #163 against main before building anything, and most of what the row asks for had already landed. /services?q= already renders the query as the <h1> through SearchResultsHeaderBand, the shortlist bar is already conditional on a non-empty selection, Compare already exists, and the four-card numbered walkthrough is mounted only on /services/[slug]tests/ui-tools.spec.ts already asserts it is absent from the results route. The current/ baseline screenshot in the comps folder is from 2026-07-31 and no longer reflects main. This PR closes the residual delta to direction B rather than rebuilding what is already there.
  • Added ServiceReferralProgress: a one-line Search / Shortlist / Compare / Refer dot rail whose active stage is derived from the existing shortlist state during render. Its accessible name is "Referral progress", deliberately not the "Referral workflow" name the removed walkthrough used, so the existing absence assertion cannot be quietly satisfied by renaming that component back onto this route. "Refer" is never the current stage here; it is reached on the record.
  • Compacted the result row by removing the Catchment / Eligibility / Cost strip and the confidence pill. Three truncated fields per row turned a scan of 45 crisis services into clipped prose; the untruncated values are one tap away on the record behind "Review referral", which is where a referral decision is actually made.
  • Added a per-row bookmark wired to account favourites, kept visually and semantically distinct from the shortlist: the bookmark persists across sessions, the shortlist is this search's working set and is deliberately not persisted. Its outcome is announced through a visible polite status region, because "Sign in or create an account to save services" is the common outcome for a guest and hiding it would leave the control looking simply broken.
  • Moved the shortlist banner below the heading it qualifies.

Deliberately unchanged, and worth stating because the comp disagrees: SearchResultsHeaderBand's count/query weighting. Direction B draws the query dominant and the count small, but that split is a documented contract (docs/search-chrome-behaviour.md, Results band rules 1–2), is shared by twelve modes, and is visual-baselined from this exact route (tests/ui-visual-baseline.spec.ts). The outcome #163 actually asks for — the <h1> is the query, not a match count — holds either way. The comp-vs-contract divergence is being captured as its own ledger row rather than resolved silently inside a services PR. Also unchanged: the Services ModeHome (this row's stop condition) and the filter contract that PR #1878 landed on 2026-08-13.

One deviation from the comp: the shortlist banner keeps "N shortlisted" rather than "N in shortlist". Same meaning, and it avoids churning two source-text assertions for no behavioural gain.

Verification

  • npm run verify:pr-local
PR-local verification summary:
- completed: check:runtime, check:installed-lock-parity, format:changed, lint, typecheck, test, build, check:rag:fixtures, check:medication-interactions, check:medication-lexicon-report
- failed: (none)
- not reached: (none)

Focused proof before that gate:

 Test Files  4 passed (4)
      Tests  22 passed (22)

(services-navigator-scope-empty-state.dom.test.tsx, audit-content-services-regressions.test.ts, search-results-band-adoption.test.ts, route-reachability.test.ts — the first two are the ones that pin this file's effect-free contract and its shortlist source text.)

Design-system contract, run because the row markup changed:

Design-system contract passed (734 production files; raw colors 2; literal shadows 0; legacy tap classes 0; edge conflicts 25; 1px shadow spreads 2).

UI verification not run: the container ships chromium-1194 while the lock pins revision 1234, so check:playwright-browser-revision fails closed and no local Playwright run is possible. Pointing PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH at the stale shell is forbidden by AGENTS.md. Browser proof for the changed journey therefore rests on the CI Production UI job, which runs ui-smoke and ui-tools; both were extended in this PR to assert the new rail's stage progression and the compacted row.

Risk and rollout

  • Risk: the row now shows less at a glance — Eligibility and Cost are no longer on the result card. That is the intended direction-B change, and both fields remain on the service record one tap away, but it is the change most worth a second opinion in review. Secondary risk is the bookmark: it writes to account favourites from a results row for the first time, so a save failure or an unauthenticated user must degrade visibly rather than silently, which is why the status region is visible rather than sr-only.
  • Rollback: single commit, revertable on its own. Nothing in it is depended on by other work.
  • Provider or production effects: None. The bookmark uses the existing /api/account/favourites endpoint already used by the service, form, and differential record pages; no new endpoint, schema, or provider call was introduced.

Clinical Governance Preflight

The classifier returns clinicalRisk: false for these paths, so this section is not required — completed anyway because the change alters which clinical fields a referral result row displays.

  • Source-backed claims still require linked source verification before clinical use
  • No patient-identifiable document workflow was introduced or expanded without explicit governance approval
  • Supabase target remains Clinical KB Database (sjrfecxgysukkwxsowpy)
  • Service-role keys and private document access remain server-only
  • Demo/synthetic content remains clearly separated from real clinical sources
  • Source metadata, review status, and outdated/unknown-source behavior remain conservative
  • Deployment classification/TGA SaMD impact was checked when clinical decision-support behavior changed

On the row-content change specifically: no service data, ranking, or source governance behaviour changed. Only which already-public fields the results row surfaces changed, and the removed fields remain reachable, untruncated, on the record.

Notes

  • RAG impact: no retrieval behaviour change — this PR touches only the services results presentation layer (services-navigator-page.tsxrendering and its tests). Retrieval, ranking, selection, and scoring are untouched;rankServiceRecords, the facet/scope pipeline, and relevanceRankMap` are all called exactly as before.
  • While running the design-system contract I found a pre-existing baseline drift unrelated to this change: legacyShadowAliases measures 118 on clean origin/main while scripts/design-system-contract-baseline.json pins 119. Verified by running the checker against the unmodified file. That is one unit of stale ratchet slack and belongs to the gate work in ledger #265, not here.

Generated by Claude Code

Ledger #163 asked for query-as-H1, a progressive shortlist/compare flow, and
no always-on decision panel or giant step rail on /services?q=. Re-measured
against main first: most of that had already landed. The query is already the
<h1> via SearchResultsHeaderBand, the shortlist bar is already conditional,
Compare already exists, and the four-card numbered walkthrough is only mounted
on /services/[slug] — ui-tools already asserts it is absent from results. The
2026-07-31 baseline screenshot in the comps folder no longer reflects main.

This closes the residual delta to direction B:

- Add ServiceReferralProgress, a one-line Search/Shortlist/Compare/Refer dot
  rail whose active stage is derived from the shortlist state during render.
  Its accessible name is "Referral progress", deliberately not the
  "Referral workflow" name the removed walkthrough used, so the existing
  absence assertion cannot be satisfied by renaming that component back onto
  this route. Refer is never current here; it is reached on the record.
- Compact the result row: drop the Catchment/Eligibility/Cost strip and the
  confidence pill. Three truncated fields per row turned a scan of 45 crisis
  services into clipped prose; the untruncated values are one tap away on the
  record, which is where a referral decision is made.
- Add a per-row bookmark wired to account favourites, kept visually and
  semantically distinct from the shortlist: the bookmark persists across
  sessions, the shortlist is this search's working set and is not persisted.
  Its outcome is announced through a visible polite status, because
  "sign in to save services" is the common guest outcome and hiding it would
  leave the control looking broken.
- Move the shortlist banner below the heading it qualifies.

Deliberately unchanged: SearchResultsHeaderBand's count/query weighting. The
comp draws the query dominant, but that split is a documented contract
(docs/search-chrome-behaviour.md, Results band rules 1-2), is shared by twelve
modes, and is visual-baselined from this exact route. The h1-is-the-query
outcome this row asked for holds either way. Also unchanged: the Services
ModeHome (this row's stop condition) and the filter contract PR #1878 landed.

Shortlist copy stays "N shortlisted" rather than the comp's "N in shortlist" —
same meaning, and it avoids churning two source-text assertions for no
behavioural gain.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XYphQZmsBBeqnidpSnAtjE
@supabase

supabase Bot commented Aug 15, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project sjrfecxgysukkwxsowpy because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@coderabbitai

coderabbitai Bot commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 25 minutes

Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7dd70bfc-83b5-46c9-bb40-899ef7f47a00

📥 Commits

Reviewing files that changed from the base of the PR and between 3dec7b3 and abc23e9.

📒 Files selected for processing (12)
  • docs/branch-review-records/216a72e41232d90b9641c9a9cf0446c884067c3339f7a2f50cd5c5e642b9988e.record.md
  • docs/branch-review-records/3fbcef2b507598e6baa40944420519cc84a4cee33bf9c809091f21ed28f76192.record.md
  • docs/branch-review-records/60422ff1c15e4237b0b0d3028b47dde0cd7d2e44c4b79c2badd5c8be19153682.record.md
  • docs/branch-review-records/badab2e50d140f081e049c934ff5e1c37b7415e4213102534a21b99bb97e87fe.record.md
  • docs/branch-review-records/d566ba015a558b6a48c81f5c8d59fd2b19edd41a2f38f86c05ae354673816ce5.record.md
  • docs/outstanding-issues-inbox/0e5573e3-425d-4253-9b28-0c1c81a4f3fe.json
  • docs/outstanding-issues-inbox/568597bd-fc9f-47d6-b582-443812115e67.json
  • src/components/services/services-navigator-page.tsx
  • tests/services-bookmark-readiness.dom.test.tsx
  • tests/services-navigator-scope-empty-state.dom.test.tsx
  • tests/ui-smoke.spec.ts
  • tests/ui-tools.spec.ts

Comment @coderabbitai help to get the list of available commands.

Travels with the owning PR rather than a ledger-only branch, per AGENTS.md
"PR bundling" — these are independent immutable files, so they carry no
conflict risk against a concurrent reconcile.

- Branch review record for f939131.
- issues:done for #163, recording the split explicitly: what was already on
  main before this PR versus what this PR delivered, and the one part left
  deliberately undone (the shared band's count/query weighting).
- issues:add for the comps-vs-contract divergence that left behind, so the
  next implementer finds a decision to make rather than a silent gap.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XYphQZmsBBeqnidpSnAtjE

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f939131860

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/components/services/services-navigator-page.tsx

BigSimmo commented Aug 15, 2026

Copy link
Copy Markdown
Owner Author

Codex review-and-fix summary

  • Final state: merged externally by the PR's pre-existing auto-merge workflow.
  • Final reviewed head: abc23e9819ecb090e520cb49f36b770783fed5d5
  • Base at merge: 3dec7b3e67e8d26a40596a44848f242e1a8dccac
  • Merge commit: 261ef4665af53b58e1ce040b9f93b9f5e56ca0ae
  • Branch update / merge tree: latest base was merged into the PR branch; the final head contains the reviewed fixes, and its merge tree against the base is clean and byte-identical to the head tree.
  • Issues fixed: prevented repeated same-row bookmark activation; serialized page-wide row bookmark mutations to avoid cross-row optimistic rollback loss; and made failed favourites loads a truthful unavailable/disabled state instead of falsely claiming rows were unsaved.
  • Adversarial review: a fresh-context Codex review reproduced both mutation races and the load-failure state, then re-reviewed the final diff and found no additional PR-introduced P0/P1/P2 issue. Residual risk is limited to browser-only layout/interaction of the compact result rows and progress rail.
  • Threads: the sole actionable review thread was replied to with the fixed head and resolved; no actionable threads remain.
  • Decisive offline checks: focused Vitest 14/14 on the reviewed implementation and 8/8 on the exact published head; source typecheck; changed-file ESLint; Prettier; git diff --check; branch-review-ledger and outstanding-issues guards.
  • Exact-head CI: required CI completed successfully; advisory SAST and Secret Scan also completed successfully. No pending or failed exact-head checks remain.
  • Blockers: none.
  • Residual risk: hosted/browser/provider-backed checks were not run locally under the requested limits; exact-head CI is green.

Codex did not merge or modify auto-merge. The existing merge workflow completed the PR.

claude and others added 3 commits August 15, 2026 09:27
… settles

AccountDataProvider initialises `ready` to `auth.status !== "authenticated"`,
so for a signed-in reader it is false until the favourites GET resolves, and
`favourites` is empty for that whole window. `isSaved()` therefore answered
"no" for every service — not because nothing was saved, but because nothing had
been read yet. The row rendered "Save X to favourites" on a service the reader
had already saved, and a tap issued a redundant write inverting a state that
was never loaded.

The control is now inert until the read settles: native `disabled` (transient
inertness, which is what docs/wiring-conventions.md reserves `disabled` for,
as against the aria-disabled placeholder pattern for permanently-unavailable
actions), no `aria-pressed` at all rather than a confidently wrong one, and an
accessible name that says it is loading. `toggleSaved` refuses early too, so a
programmatic call cannot invert an unread state either.

Regression cover in tests/services-bookmark-readiness.dom.test.tsx, mutation-
verified: reverting the gate fails the first case and leaves the second
passing, so the test discriminates the defect rather than the feature.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XYphQZmsBBeqnidpSnAtjE
Record 216a72e4 on this branch claimed "Fix service bookmark readiness and
mutation race" at head 720e7027a9f08e518eb6344e74dfde35d78d5981. Verified
against the refs rather than taken at face value, per AGENTS.md "Third-party
fix claims stay unverified until checked":

- git cat-file -t 720e7027... — object does not exist in this repository.
- git diff 285e12d..87e7fcc -- src/components/services/ — empty. No code
  change had landed under that claim.

The ledger records are immutable, so this supersedes rather than edits. The
defect the record named was real, and the preceding commit fixes it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XYphQZmsBBeqnidpSnAtjE
@BigSimmo
BigSimmo enabled auto-merge (squash) August 15, 2026 12:56
@BigSimmo
BigSimmo merged commit 261ef46 into main Aug 15, 2026
26 checks passed
@BigSimmo
BigSimmo deleted the claude/services-search-redesign-163 branch August 15, 2026 13:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants